#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>

#define GPIO_MUX_2_ADDR 0X16000498
#define MAP_SIZE 4096UL //映射的页大小
#define MAP_MASK (MAP_SIZE - 1)

int gpio_mux (off_t target,unsigned long writeval)//操作寄存器复用的函数 第一个参数是寄存器的地址 第二个是要修改的值
{
    int fd;
    void *map_base, *virt_addr;

    if ((fd = open("/dev/mem",O_RDWR | O_SYNC)) == -1)
    {
        fprintf(stderr,"Error at line %d, file %s (%d) [%s]\n",__LINE__,__FILE__,errno,strerror(errno));
        return -1;
    }

    map_base = mmap(0,MAP_SIZE,PROT_READ | PROT_WRITE, MAP_SHARED,fd, target & ~MAP_MASK );//把物理地址映射成虚拟地址
    if(map_base == (void *) -1)
    {
        fprintf(stderr,"Error at line %d, file %s (%d) [%s]\n",__LINE__,__FILE__,errno,strerror(errno));
        return -1;
    }

    virt_addr = map_base + (target & MAP_MASK); //这个就是我们要操作的虚拟地址
    *((unsigned long *) virt_addr) = writeval; //通过给虚拟地址赋值，就可以实现操作寄存器的值
    

        // 释放映射内存
    if (munmap(map_base, MAP_SIZE) == -1) {
        fprintf(stderr, "Error unmapping memory at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno));
        return -1;
    }

    // 关闭文件描述符
    if (close(fd) == -1) {
        fprintf(stderr, "Error closing file descriptor at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno));
        return -1;
    }

    return 0;

}

int main(int argc,char **argv)
{
    if(argc < 2)
    {
        fprintf(stderr, "\nUsage:\t%s { op_type }\n"
            "\top_type    : 1.mian; 0.gpio\n\n",
            argv[0]);
        exit(1);

    }

    if(strtoul(argv[1],0,10) == 1)
    {
        gpio_mux(GPIO_MUX_2_ADDR,0xFFFFFFFF);// 42 43 还原为主功能
    }

    if(strtoul(argv[1],0,10) == 0)
    {
        gpio_mux(GPIO_MUX_2_ADDR,0xF00FFFFF); //42 43 复用为gpio口
    }
    return 0;
}